package xyz.zchao.blog.util;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * @Description: AES加密算法的ECB模式加密并解密
 * @Author: guozongchao
 * @Date: 2020/5/7 0:05
 */
public class EncryptionUtil {
    //128位密钥
    private static final String KEY="dsdf59ahfjf.?/#*dkdxkfnds4621dsd";
    //编码类型
    private static final String CHARSET="UTF-8";

    /**
     * 返回加密后密文字符串
     * @param data
     * @return
     * @throws GeneralSecurityException
     */
    public static String encrypted(String data) throws Exception {
        return Base64.getEncoder().encodeToString(encrypt(KEY.getBytes(CHARSET),data.getBytes(CHARSET)));
    }

    /**
     * 返回解密后明文字符串
     * @param encrypted
     * @return
     * @throws Exception
     */
    public static String decrypted(String encrypted) throws Exception {
        return new String(decrypt(KEY.getBytes(CHARSET),Base64.getDecoder().decode(encrypted)), CHARSET);
    }

    /**
     * 加密，返回字节数组
     * @param key
     * @param input
     * @return
     * @throws GeneralSecurityException
     */
    public static byte[] encrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        // CBC模式需要生成一个16 bytes的initialization vector:
        SecureRandom sr = SecureRandom.getInstanceStrong();
        byte[] iv = sr.generateSeed(16);
        IvParameterSpec ivps = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivps);
        byte[] data = cipher.doFinal(input);
        // IV不需要保密，把IV和密文一起返回:
        return join(iv, data);
    }

    /**
     * 解密，返回字节数组
     * @param key
     * @param input
     * @return
     * @throws GeneralSecurityException
     */
    public static byte[] decrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        // 把input分割成IV和密文:
        byte[] iv = new byte[16];
        byte[] data = new byte[input.length - 16];
        System.arraycopy(input, 0, iv, 0, 16);
        System.arraycopy(input, 16, data, 0, data.length);
        // 解密:
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        IvParameterSpec ivps = new IvParameterSpec(iv);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivps);
        return cipher.doFinal(data);
    }

    private static byte[] join(byte[] bs1, byte[] bs2) {
        byte[] r = new byte[bs1.length + bs2.length];
        System.arraycopy(bs1, 0, r, 0, bs1.length);
        System.arraycopy(bs2, 0, r, bs1.length, bs2.length);
        return r;
    }

/*
    public static void main(String[] args) throws Exception {
        System.out.println(encrypted("123456"));
    }
*/

}
